package de.bht.fb6.cg1.exercise2;

import ij.IJ;
import ij.ImagePlus;
import ij.gui.GenericDialog;
import ij.gui.NewImage;
import ij.plugin.PlugIn;
import ij.process.ImageProcessor;

/**
 * This class represents a plug in for ImageJ. It removes color components from an image.
 * 
 * @author Stephan Rehfeld <rehfeld (-at-) beuth-hochschule.de >
 */
public class BrightnessModifier implements PlugIn {

	/**
	 * The ImagePlus object of the loaded image.
	 */
	private final ImagePlus imp;
	
	/**
	 * This main method stars ImageJ and applies this plug in to the loaded image.
	 * 
	 * @param args Ignored.
	 */
	public static void main( final String args[] ) {
		IJ.open( "test.jpg" );
		final BrightnessModifier rgbComponentRemover = new BrightnessModifier( IJ.getImage() );
		rgbComponentRemover.run( "" );
	}

	/**
	 * This constructor creates a new RGBComponentRemover.
	 * 
	 * @param imp The ImagePlus object. Must not be null!
	 */
	public BrightnessModifier( final ImagePlus imp ) {
		if( imp == null ) {
			throw new IllegalArgumentException( "The parameter 'imp' must not be null!" );
		}
		this.imp = imp;
	}
	
	@Override
	public void run( final String arg ) {
		imp.show();
		
		final GenericDialog gd = new GenericDialog( "Remove Components" );
		gd.addSlider("brightness", -255, 255, 0);
		gd.showDialog();
		
		final int modify = new Double(gd.getNextNumber()).intValue();
		
		final ImageProcessor ipOld = imp.getProcessor();
		final ImagePlus newImage = NewImage.createRGBImage( "Skaliertes Bild", ipOld.getWidth(), ipOld.getHeight(), 1, NewImage.FILL_BLACK );
		
		final ImageProcessor ipNew = newImage.getProcessor();
		
		final int[] pixOld = (int[])ipOld.getPixels();
		final int[] pixNew = (int[])ipNew.getPixels();
		
		// add the brightness to the single color values
		for( int i = 0; i < pixNew.length; ++i ) {
			final int r = trim(((pixOld[ i ] & 0x00ff0000) >> 16) + modify);
			final int g = trim(((pixOld[ i ] & 0x0000ff00) >> 8) + modify);
			final int b = trim((pixOld[ i ] & 0x000000ff) + modify);
			
			pixNew[ i ] = (0xff << 24) | r << 16 | g << 8 | b;
		}
		
		newImage.show();
	}
	
	/**
	 * transforms a value in the range of 0-255
	 * 
	 * if the value is < 0 it'll be 0
	 * 
	 * if the value is > 255 it'll be 255
	 * @param value value to transform
	 * @return integer between 0 and 255
	 */
	private int trim(int value) {
		if (value < 0) return 0;
		if (value > 255) return 255;
		return value;
	}
	
}
